package com.bubblegumproject.ogo.action;

import java.util.Deque;
import java.util.ArrayDeque;
import java.util.Iterator;
import java.io.Serializable;

/**
 * Contains all the errors that occured during the processing of an error. Because Action processing is often
 * asynchronously or invoked directly each Action must define its own error protocol (those errors that can and have
 * occured during processing). Action handlers should include push errors onto the stack while other clients may access
 * the stack to quickly which, if any, errors occurred during action processing.
 *
 * @author Azubuko Obele (buko.obele@gmail.com)
 */
public class ActionErrorStack implements Serializable {

    private Deque<ActionError> errors = new ArrayDeque<ActionError>();

    public void push(Throwable error) {
        assert(error != null);
        errors.push(new ActionError(error));
    }

    public Iterator<ActionError> list() {
        return errors.iterator();
    }

    public boolean contains(Class<? extends Throwable> clazz) {
        assert(clazz != null);
        for (ActionError e : errors) {
            if (e.getThrowable() != null && clazz.isAssignableFrom(e.getThrowable().getClass())) return true;
        }
        return false;
    }

    /**
     * Check to see if an error occurred during Action processing. If the error did occur it will be thrown.
     *
     * @param clazz class of the error to check for
     * @throws T exception of type <code>class</code> if it did occur
     */
    public <T extends Throwable> void check(Class<T> clazz) throws T {
        assert(clazz != null);
        for (ActionError e : errors) {
            if (e.getThrowable() != null && clazz.isAssignableFrom(e.getThrowable().getClass()))
                throw clazz.cast(e.getThrowable());
        }
    }
}
